#pragma once
#include "../common/dispatcher.hpp"
#include "../client/rpc_client.hpp"
#include "rpc_topic.hpp"
#include "rpc_router.hpp"
#include "rpc_registry.hpp"

//Rpc服务的提供
//服务注册与发现的服务提供者和服务发现者的管理
//rpc服务提供服务端
//注册中心服务端
namespace rpc
{
    namespace server
    {
        //注册中心服务端->一个单纯的服务端->业务就是提供者和发现者的管理->针对服务发现/服务注册
        class RegistryServer
        {
        public:
            using ptr = std::shared_ptr<RegistryServer>;
            //监听端口
            RegistryServer(int port) :
             _pd_manager(std::make_shared<PDManager>()),          
             _dispatcher(std::make_shared<rpc::Dispatcher>())
            {
                //服务注册与发现回调
                auto service_cb = std::bind(&PDManager::onServiceRequest, _pd_manager.get(),std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<ServiceRequest>(MType::REQ_SERVICE, service_cb);
                _server = rpc::ServerFactory::create(port);
                auto message_cb = std::bind(&rpc::Dispatcher::onMessage, _dispatcher.get(),std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);
                //连接断开的回调
                auto close_cb = std::bind(&RegistryServer::onConnShutdown, this, std::placeholders::_1);
                _server->setCloseCallback(close_cb);
            }

            //启动服务器
            void start()
            {
                _server->start();
            }

        private:
            //连接关闭的回调函数
            void onConnShutdown(const BaseConnection::ptr &conn)
            {
                _pd_manager->onConnShutdown(conn);
            }

        private:
            PDManager::ptr _pd_manager;//服务管理
            Dispatcher::ptr _dispatcher;//路由转发
            BaseServer::ptr _server;//服务端
        };

        //Rpc服务端->包含一个Rpc服务端,一个服务注册客户端,针对Rpc请求进行处理,向服务中心进行服务注册
        class RpcServer
        {
        public:
            using ptr = std::shared_ptr<RpcServer>;
            // rpc——server端有两套地址信息：
            //   1. rpc服务提供端地址信息--必须是rpc服务器对外访问地址（云服务器---监听地址和访问地址不同）
            //   2. 注册中心服务端地址信息 -- 启用服务注册后，连接注册中心进行服务注册用的
            RpcServer(const Address &access_addr,
                      bool enableRegistry = false,
                      const Address &registry_server_addr = Address()) : 
                      _enableRegistry(enableRegistry),                                                
                      _access_addr(access_addr),                                              
                      _router(std::make_shared<rpc::server::RpcRouter>()),                          
                      _dispatcher(std::make_shared<rpc::Dispatcher>())
            {
                if (enableRegistry)//需要服务注册
                {
                    _reg_client = std::make_shared<client::RegistryClient>(registry_server_addr.first, registry_server_addr.second);
                }
                // 当前成员server是一个rpcserver，用于提供rpc服务的->接收Rpc请求
                auto rpc_cb = std::bind(&RpcRouter::onRpcRequest, _router.get(),std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<rpc::RpcRequest>(rpc::MType::REQ_RPC, rpc_cb);//进行分发处理

                _server = rpc::ServerFactory::create(access_addr.second);//监听对应的端口的所有主机地址
                auto message_cb = std::bind(&rpc::Dispatcher::onMessage, _dispatcher.get(),std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);
            }

            //服务注册->对服务进行注册->连接注册中心
            void registerMethod(const ServiceDescribe::ptr &service)
            {
                if (_enableRegistry)
                {
                    _reg_client->registryMethod(service->method(), _access_addr);//启动了服务注册,进行服务注册
                }
                _router->registerMethod(service);
            }

            //启动服务器
            void start()
            {
                _server->start();
            }

        private:
            bool _enableRegistry;//是否启用服务注册
            Address _access_addr;//外部的访问地址,提供rpc服务的地址
            client::RegistryClient::ptr _reg_client;//注册客户端
            RpcRouter::ptr _router;//根据方法进行映射
            Dispatcher::ptr _dispatcher;//根据类型进行映射
            BaseServer::ptr _server;//服务端
        };

        //主题服务器
        class TopicServer
        {
        public:
            using ptr = std::shared_ptr<TopicServer>;
            TopicServer(int port)
            :_topic_manager(std::make_shared<TopicManager>()),
            _dispatcher(std::make_shared<rpc::Dispatcher>())
            {
                auto topic_cb = std::bind(&TopicManager::onTopicRequest,_topic_manager.get(),std::placeholders::_1,std::placeholders::_2);
                _dispatcher->registerHandler<TopicRequest>(MType::REQ_TOPIC,topic_cb);
                _server = rpc::ServerFactory::create(port);
                auto message_cb = std::bind(&rpc::Dispatcher::onMessage,_dispatcher.get(),std::placeholders::_1,std::placeholders::_2);
                _server->setMessageCallback(message_cb);
                auto close_cb = std::bind(&TopicServer::onConnShutdown,this,std::placeholders::_1);
                _server->setCloseCallback(close_cb);

            }

            void start()
            {
                _server->start();
            }
        private:
            void onConnShutdown(const BaseConnection::ptr & conn)
            {
                _topic_manager->onShutdown(conn);
            }
        private:
            TopicManager::ptr _topic_manager;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };

    }
}